#include <QTextCodec>
#include <QStringList>
#include <QTimerEvent>

#include "IrcSocket.h"

IrcSocket::IrcSocket(QObject* parent) : QTcpSocket(parent) {
	//устанавливаем начальные значения переменных
	tail = "";
	needconnect = true;

	//подключаемся к сигналу получения данных
	connect(this, SIGNAL(readyRead()), this, SLOT(SocketReadyRead()));
	//подключаемся к сигналу получения ошибки соединения
	connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketError()));
	//подключаемся к сигналу закрытия соединения
	connect(this, SIGNAL(disconnected()), this, SLOT(SocketDisconnect()));
	//подключаемся к сигналу установки соединения
	connect(this, SIGNAL(connected()), this, SLOT(SocketDisconnect()));
}

IrcSocket::~IrcSocket() {
	//все выключаем и закрываем
	Disconnect();
}

void IrcSocket::GetSocketData(SocketData& sd_) {
	//выдаем данные
	sd_ = socketdata;
}

void IrcSocket::SetSocketData(const SocketData& sd_) {
	//сохраняем данные
	socketdata = sd_;
	//проверяем что нам дали
	if (socketdata.timeout < 1) { socketdata.timeout = 120; }
	if (socketdata.rectime < 1) { socketdata.rectime = 60; }
	//настраиваем кодировку
	if (!socketdata.codepage.isEmpty()) {
//!		setCodec(QTextCodec::codecForName(codepage));
	}
}

void IrcSocket::SocketReadyRead() {
	//перезапускаем таймер ожидания данных от сервера
	killTimer(to_timer);
	to_timer = startTimer(socketdata.timeout*1000);
	//считываем все полученные данные
	QByteArray ba = readAll();
	//преобразуем в строку
//! тут тоже надо посмотреть, может как то возможно указать кодировку прям сокету
	QString indata = QTextCodec::codecForName(socketdata.codepage.toAscii())->toUnicode(ba);
	//прибавляем в начало то, что осталось от прошлых данных.
	indata = tail + indata;
	//обнуляем буфер
	tail = "";
	//разбиваем на строки
	QStringList str = indata.split("\n");
	//считаем количество элементов
	int c = str.count();
	//проверяем что в конце данных есть перенос строки
	if (!indata.endsWith("\x0D\x0A") && !indata.endsWith('\n')) {
		 //сохраняем неполные данные в буфер и уменьшаем кол-во строк на 1
		 c = c - 1;
		 tail = str[c];
	}
	//перебираем все строки
	for (int i=0; i<c; i++) {
		//чистим от мусора
		str[i].replace("\x0A", "");
		str[i].replace("\x0D", "");
		//посылаем сигнал что пришли данные
		emit GetData(str[i]);
	}
}

void IrcSocket::Connect(int& res) {
	//проверяем подключены ли мы уже
/*!	if () {
		return;
	}*/
	//если сказали что надо подключиться, то ставим флаг что надо и переподключаться
	needconnect = true;

	//проверяем что все данные для подключения корректные
	if (socketdata.host.isEmpty() || socketdata.port.isEmpty() ||
		socketdata.nick.isEmpty() || socketdata.ident.isEmpty() ||
		socketdata.realname.isEmpty() || socketdata.codepage.isEmpty())
	{
		//если данные некорректные, то не надо чтобы сокет пытался переподключиться
		needconnect = false;

		res = 1;
		return;
	}
	
	//подключаемся
	connectToHost(socketdata.host, socketdata.port.toInt());

	//останавливаем таймер ожидания данных от сервера
	killTimer(to_timer);
	//запускаем таймер ожидания данных от сервера
	to_timer = startTimer(socketdata.timeout*1000);

//! надо к библиотеке CoreError еще подключиться
	res = 0;
}

void IrcSocket::Connect(bool& res) {
	int r;
	Connect(r);
	res = (r <= 0);
}

void IrcSocket::Connect() {
	int r;
	Connect(r);
}

void IrcSocket::Disconnect(int& res) {
	//проверяем подключены мы или нет
/*!	if () {
		//! надо к библиотеке CoreError еще подключиться
		res = -1;
		return;
	}*/
	//если сказали что надо подключиться, то ставим флаг что переподключаться не надо
	needconnect = false;
	//останавливаем все таймеры
	killTimer(to_timer);
	killTimer(co_timer);
	//закрываем сокет
//!	clearPendingData();
	close();

//! надо к библиотеке CoreError еще подключиться
}

void IrcSocket::Disconnect(bool& res) {
	int r;
	Disconnect(r);
	res = (r <= 0);
}

void IrcSocket::Disconnect() {
	int r;
	Disconnect(r);
}

void IrcSocket::timerEvent(QTimerEvent *event)
{
	//проверяем что за таймер
	int id = event->timerId();
	if ( id == to_timer ) {
		//проверяем что это таймер ожидания данных от сервера
		//! тут надо не дисконнект, надо просто закрывать сокет
		Disconnect();
	} else if ( id == co_timer ) {
		//проверяем что это таймер переподключения к серверу
			Connect();
	}
}

void IrcSocket::SocketDisconnected() {
	//сбрасываем то что могло остаться в буфере
	tail = "";
	//останавливаем таймер ожидания данных от сервера
	killTimer(to_timer);
	//проверяем надо ли соединяться обратно после разрыва соединения
	if (needconnect) {
//! дописать действия для переподключения 
	}
}

void IrcSocket::SocketError() {
	//посылаем сигнал об ошибке подключения
	emit Error();
	//вызываем обработку при отключении от сервера
	SocketDisconnect();
}

void IrcSocket::SocketConnected() {
	//сбрасываем то что могло остаться в буфере
	tail = "";
	//останавливаем таймер ожидания данных от сервера
	killTimer(to_timer);
	//запускаем таймер ожидания данных от сервера
	to_timer = startTimer(socketdata.timeout*1000);
}

void IrcSocket::Send(const QString& data) {
	//проверяем что мы вообще подключены к серверу
/*	if (state != ...) {
		return;
	}*/
	//сохраняем данные локально
	QString senddata = data;
	//посылаем сигнал передачи данных
	emit SendData(senddata);
	//проверяем что данные не пустые
	if (senddata.isEmpty()) {
		return;
	}
	//делаем чтобы в конце точно был "конец строки"
	// надо тут подумать, потому что вместо одного сообщения может получиться больше
	// и тогда так заменять нельзя
//	senddata.replace("\x10","");
//	senddata.replace("\x13","");
//	senddata += "\n";

	//передаем данные на сервер
//	QTextStream os(socket);
//	os.setCodec(QTextCodec::codecForName(codepage));
//	os << text;
	//или
//	write(text);


//	send(data);
}
